#include "head.h"
#include <sys/sendfile.h>

int send_small_file(int net_fd,int file_fd,int file_size)
{
    int cur_size=0;
    int send_size=0;
    self_defined_pro_t *sdp=(self_defined_pro_t *)calloc(1,sizeof(self_defined_pro_t));

    while(send_size<file_size)
    {
        cur_size=(file_size-send_size)<1024?file_size-send_size:1024;
        bzero(sdp->message,sizeof(sdp->message));
        read(file_fd,sdp->message,cur_size);

        int ret =send(net_fd,sdp->message,cur_size,MSG_NOSIGNAL);
        if(ret<=0){
            return ret;
        }
        send_size+=cur_size;

    }
    free(sdp);
    return file_size;
}


int send_large_file(int net_fd,int file_fd,int offset,int file_size)
{
    off_t send_size =0;
    off_t cur_size=0;

    while(send_size<file_size)
    {
        if(file_size-send_size<4096)
        {
            cur_size=file_size-send_size;

        }
        else
        {
            cur_size=4096;
        }

        char * p=(char *) mmap(NULL,cur_size,PROT_READ|PROT_WRITE,MAP_SHARED,file_fd,0);

        int ret=send(net_fd,p,cur_size,MSG_NOSIGNAL);
        if(ret<=0)
        {
            return ret;
        }
        munmap(p,cur_size);

        send_size+=cur_size;
    }
    return file_size;
}


int do_upload(client_status_t *cs)
{  
    int net_fd = cs->socket_fd ;

    char command[60]={0};

    //切割命令 找出文件名
    strcpy(command,cs->runtime_cmd);
    char *file_name = strtok(command," ");
    file_name=strtok(NULL, " ");

    //  注意判断文件是否存在
    int file_fd = open(file_name,O_RDWR);

    if(file_fd<0)
    {
        printf("文件打开失败\n");
        return 0;
    }


    // 发送信息
    self_defined_pro_t *mes=(self_defined_pro_t *)calloc(1,sizeof(self_defined_pro_t));
    mes->cmd=upload;
    mes->para_num=3;

    strcat(mes->message,"username=");
    strcat(mes->message,cs->user );
    strcat(mes->message,"&");
    strcat(mes->message,"path=");
    strcat(mes->message,cs->path);
    strcat(mes->message,"&");
    strcat(mes->message,"filename=");
    strcat(mes->message,file_name);
    mes->message_len=strlen(mes->message);
    int ret = send(net_fd,mes,sizeof(self_defined_pro_t),MSG_NOSIGNAL);
    ERROR_CHECK(ret, -1, "send");

    // 传输文件大小
    struct stat stat_file;
    fstat(file_fd,&stat_file);
    int file_size=stat_file.st_size;
    send(net_fd,&file_size,sizeof(int),MSG_NOSIGNAL);

    // 接收服务端返回, 高速我客户端到低是断点续传  还是新文件上传o
    self_defined_pro_t *server_mes=(self_defined_pro_t *)calloc(1,sizeof(self_defined_pro_t));
    recv(net_fd,server_mes,sizeof(self_defined_pro_t),MSG_WAITALL);

    if(server_mes->cmd == 200){
        // 新文件上传
        //根据文件大小判断传递方式
        if(file_size>=1000000)
        {//大文件传递
            send_large_file(net_fd,file_fd,0,file_size);
        }
        else{
            //小文件传递
            send_small_file(net_fd,file_fd,file_size);
        }
        memset(server_mes, 0, sizeof(self_defined_pro_t));
        recv(net_fd,server_mes,sizeof(self_defined_pro_t),MSG_WAITALL);
        if(server_mes->cmd == 200){
            printf("文件上传成功 \n");
            return  0;
        }
    }else if (server_mes->cmd == 210){
        // 断点上传逻辑
        // 获取服务器的文件大小
        char *str=strtok(server_mes->message,"=");
        str=strtok(NULL,"&");

        off_t server_file_size = atoi(str);
        sendfile(net_fd, file_fd, &server_file_size, file_size-server_file_size);

    }else if(server_mes->cmd == 220){
        printf("无需上传, 文件已经存在 \n");
    }

}

